package cn.com.pc.content.service;

import cn.com.pc.content.domain.*;
import cn.com.pc.content.domain.content.Content;
import cn.com.pc.content.domain.content.ContentRepository;
import cn.com.pc.content.domain.content.ContentType;
import cn.com.pc.content.service.es.ESCurdService;
import cn.com.pc.content.service.es.ESQueryService;
import cn.com.pc.content.service.es.ElasticEntity;
import cn.com.pc.content.util.ElasticUtil;
import cn.com.pc.content.util.JsonUtils;
import com.fasterxml.jackson.core.type.TypeReference;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.search.*;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.search.Scroll;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.util.*;

@Slf4j
@Service
public class ContentImportService {

    @Autowired
    private ESQueryService esQueryService;

    @Autowired
    private ESCurdService esCurdService;

    @Autowired
    private ContentRepository contentRepository;

    @Autowired
    private ContentService contentService;

    /**
     * 从pcp导入没打的标签
     */
    public void updateContentFromPcpES() {
        for (String indexName : Arrays.asList("pcp_pconline_article", "pcp_pconline_video", "pcp_pconline_short_message")) {
//            // 补打tagBy
//            BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery().should(QueryBuilders.boolQuery().mustNot(QueryBuilders.existsQuery("taggedBy"))).should(QueryBuilders.boolQuery().filter(QueryBuilders.termQuery("taggedBy.keyword", "")).must(QueryBuilders.existsQuery("taggedBy")));
            // 补打tagIds
            BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery().mustNot(QueryBuilders.existsQuery("tagIds"));

            SearchSourceBuilder searchSourceBuilder = ElasticUtil.initSearchSourceBuilder(boolQueryBuilder);
            final Scroll scroll = new Scroll(TimeValue.timeValueHours(1));
            SearchRequest request = new SearchRequest(indexName);
            request.source(searchSourceBuilder);
            request.scroll(scroll);
            try {
                SearchResponse searchResponse = esQueryService.search(request);
                // 记录当前页scrollId
                String scrollId = searchResponse.getScrollId();
                SearchHit[] searchHits = searchResponse.getHits().getHits();
                long totalHits = searchResponse.getHits().getTotalHits().value;
                log.info("es查询集合总数为{}", totalHits);
                ClearScrollRequest clearScrollRequest = new ClearScrollRequest();

                ElasticEntity elasticEntity = null;
                int i = 0;
                while (searchHits != null && searchHits.length > 0) {
                    if (StringUtils.hasLength(scrollId)) {
                        clearScrollRequest.addScrollId(scrollId);
                    }
                    for (SearchHit hit : searchResponse.getHits().getHits()) {
                        elasticEntity = new ElasticEntity();
                        elasticEntity.setId(hit.getId());
                        elasticEntity.setData(hit.getSourceAsMap());
                        this.updateContentTagBy(elasticEntity, indexName);
                        i += 1;
                    }
                    // 根据scrollId发scroll请求获取下一页内容
                    searchResponse = esQueryService.searchScrollResponse(new SearchScrollRequest(scrollId).scroll(scroll));
                    scrollId = searchResponse.getScrollId();
                    searchHits = searchResponse.getHits().getHits();
                }

                log.info("完成修改索引{}，共修改{}条", indexName, i);
                if(elasticEntity != null) {
                    esQueryService.clearScroll(scrollId);
                }

            } catch (IOException e) {
                e.printStackTrace();
                log.error(e.getMessage());
            }
        }
    }

    private void updateContentTagBy(ElasticEntity entity, String indexName) {
        // 在Pcp中查找
        String referId = entity.getData().get("referId").toString();
        String id = entity.getId();
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery().must(QueryBuilders.existsQuery("tagIds")).must(QueryBuilders.termQuery("sourceId", referId));
        SearchSourceBuilder pcpSearchSourceBuilder = ElasticUtil.initSearchSourceBuilder(queryBuilder);
        SearchHit[] pcp_items = esQueryService.search(pcpSearchSourceBuilder, "pcp_item");

        // 修改pc-content的内容
        if (pcp_items.length > 0) {
            Map<String, Object> sourceAsMap = pcp_items[0].getSourceAsMap();
            ContentType contentType;
            switch (indexName) {
                case ("pcp_pconline_article"): {
                    contentType = ContentType.Article;
                    break;
                }
                case ("pcp_pconline_video"): {
                    contentType = ContentType.Video;
                    break;
                }
                default: {
                    contentType = ContentType.ShortMessage;
                }
            }
            try {
                Content content = contentService.getContentByReferId(referId, Site.PCOnline, Biz.PGC, contentType);
                if (content == null) {
                    log.warn("referId:{}查询失败", referId);
                    return;
                }

                RestStatus restStatus = esCurdService.update(indexName, id, new HashMap<>() {{
                    put("taggedBy", sourceAsMap.get("tagBy"));
                    put("taggedAt", sourceAsMap.get("tagAt"));
                    put("tagIds", sourceAsMap.get("tagIds"));
                    put("tagNames", sourceAsMap.get("tags"));
                }});

                if (restStatus.getStatus() == RestStatus.OK.getStatus()) {
                    log.info("referId:{}修改taggedBy成功", referId);
                    Set<Long> tagIds = JsonUtils.jsonToObj(JsonUtils.obj2String(sourceAsMap.get("tagIds")), new TypeReference<Set<Long>>() {
                    });
                    content.setTagIds(tagIds);
                    contentRepository.save(content);
                }
            } catch (IOException e) {
                log.warn("referId:{}修改taggedBy失败", referId);
                e.printStackTrace();
            }
        }
    }
}
